#include "net/acceptor.h"
#include "net/poller.h"
#include "net/socket.h"
#include "net/socket_opt.h"
#include "net/tcp_server.h"

namespace net {

bool Acceptor::Listen(const Addr &addr) {
  if (accept_socket_.get() != NULL) return false;
  accept_socket_.reset(new Socket(sock::CreateSocket()));
  accept_socket_->SetBlock(false);
  sock::TrunOffOpt(accept_socket_.get(), SOL_SOCKET, SO_KEEPALIVE);

  if (!sock::Bind(accept_socket_.get(), addr)) {
    accept_socket_.reset();
    return false;
  }

  return sock::Listen(accept_socket_.get());
}

bool Acceptor::EnableRead() {
  ev_->fd = accept_socket_->Fd();
  if (ev_->fd == -1) return false;
  ev_->arg = this;
  ev_->cb = HandleRead;

  return poller_->Add(ev_.get(), EV_READ);
}

Socket* Acceptor::Accept() {
  Addr addr;
  int32 fd = sock::Accept(accept_socket_.get(), &addr);
  if (fd == -1) {
    return NULL;
  }

  Socket* sock = Socket::CreateSocket(fd);
  sock->SetRemoteAddr(addr);
  sock->SetLocalAddr(sock::GetSockAddr(sock, true));
  sock->SetBlock(false);
  sock::TrunOffOpt(accept_socket_.get(), SOL_SOCKET, SO_KEEPALIVE);

  return sock;
}

//static methord...
void Acceptor::HandleRead(int fd, void* arg, int event) {
  Acceptor* acceptor = (Acceptor*) arg;
  CHECK(acceptor != NULL && event == EV_READ);
  Socket* sock = acceptor->Accept();
  if (sock == NULL) {
    return;
  }

  TcpServer* tcp_server = acceptor->Owner();
  tcp_server->AddConnection(sock);
}
}
